//
// Created by alexa on 5/14/2024.
//

#include "BattalionsMenu.h"
#include "../../keydown-handler/KeydownHandler.h"
#include "../../valid-input/ValidInput.h"
#include <conio.h>

void BattalionsMenu::displayMenu() {
    printMenu();
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this]() {
                ui->toggleLocale();
                return displayMenu();
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::MAIN_MENU);
                return;
            }},
            {Keys::KEY_1, [this]() {
                return displayBattalionList();
            }},
            {Keys::KEY_2, [this]() {
                return findAndDisplayBattalionInfo();
            }},
            {Keys::KEY_3, [this]() {
                return createBattalion();
            }},
            {Keys::KEY_4, [this]() {
                Battalion *battalion = findBattalion();
                return deleteBattalion(battalion);
            }}
    });
}

BattalionsMenu::BattalionsMenu(i18n::Translator *t, UserInterface *ui, BattalionsService *service) : Menu(t, ui),
                                                                                                     service(service) {}

Battalion *BattalionsMenu::findBattalion() {
    cout << endl;
    string battalionId = vi::inputString((*t)("enter-battalion-id", "battalions.general"));
    try {
        return service->getById(battalionId);
    } catch (EntityNotFound e) {
        cout << (*t)("battalion-doesnt-exist", "battalions.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        ui->setCurrentPage(Pages::BATTALIONS_MENU);
        return nullptr;
    }
}

void BattalionsMenu::displayBattalionList() {
    vector<Battalion *> battalions = service->getAll();
    printBattalionList(battalions);
    cout << endl << (*t)("get-info", "battalions.list") << endl;
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this]() {
                ui->toggleLocale();
                return displayBattalionList();
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::BATTALIONS_MENU);
                return;
            }},
            {Keys::KEY_I, [this]() {
                return findAndDisplayBattalionInfo();
            }}
    });
}

void BattalionsMenu::deleteBattalion(Battalion *battalion) {
    if (!battalion) return;
    service->deleteOne(battalion->getId());
    cout << (*t)("successfully-deleted", "battalions.delete", {{"battalion-id", battalion->getId()}}) << endl;
    cout << (*t)("continue", "general");
    _getch();
    ui->setCurrentPage(Pages::BATTALIONS_MENU);
}

void BattalionsMenu::printBattalionList(vector<Battalion *> list) {
    clearScreen();
    printKeybinds();
    cout << (*t)("title", "battalions.list") << endl;
    if (list.empty()) {
        cout << (*t)("empty-list", "general") << endl;
        return;
    }
    for (const auto &battalion: list) {
        cout << endl;
        cout << (*t)("id", "battalions.info") << ": " << battalion->getId() << endl;
        cout << (*t)("name", "battalions.info") << ": " << battalion->getName() << endl;
        cout << (*t)("units-number", "battalions.info") << ": " << battalion->getAllUnitsIds().size() << endl;
    }
}

void BattalionsMenu::printBattalionInfo(Battalion *battalion, vector<CombatUnit *> units) {
    clearScreen();
    printKeybinds();
    cout << endl;
    cout << (*t)("id", "battalions.info") << ": " << battalion->getId() << endl;
    cout << (*t)("name", "battalions.info") << ": " << battalion->getName() << endl;
    cout << endl << (*t)("units", "battalions.info") << ": " << endl;
    if (units.empty()) {
        cout << (*t)("no-units", "battalions.info") << endl;
    } else {
        for (const auto &unit: units) {
            cout << (*t)("id", "units.info") << ": " << unit->getId() << endl;
            cout << (*t)("name", "units.info") << ": " << unit->getName() << endl;
            cout << endl;
        }
    }
}

void BattalionsMenu::printMenu() {
    clearScreen();
    printKeybinds();
    cout << (*t)("title", "units.main") << endl;
    cout << "1. " << (*t)("option1", "battalions.main") << endl;
    cout << "2. " << (*t)("option2", "battalions.main") << endl;
    cout << "3. " << (*t)("option3", "battalions.main") << endl;
    cout << "4. " << (*t)("option4", "battalions.main") << endl;
    cout << (*t)("select-action", "general",
                 {
                         {"min", "1"},
                         {"max", "4"}
                 });
}

void BattalionsMenu::createBattalion() {
    clearScreen();
    string name = vi::inputString((*t)("enter-name", "battalions.create"));
    Battalion *battalion = service->createOne(name);
    return displayBattalionInfo(battalion);
}

void BattalionsMenu::removeUnitFromBattalion(Battalion *battalion) {
    string unitId = vi::inputString((*t)("enter-unit-id", "units.general"));
    try {
        service->removeCombatUnit(battalion->getId(), unitId);
        cout << (*t)("unit-removed", "battalions.info", {{"unit-id", unitId}}) << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayBattalionInfo(battalion);
    } catch (EntityNotFound e) {
        cout << (*t)("unit-doesnt-exist", "units.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayBattalionInfo(battalion);
    }
}

void BattalionsMenu::addUnitToBattalion(Battalion *battalion) {
    string unitId = vi::inputString((*t)("enter-unit-id", "units.general"));
    try {
        service->addCombatUnit(battalion->getId(), unitId);
        cout << (*t)("unit-added", "battalions.info", {{"unit-id", unitId}}) << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayBattalionInfo(battalion);
    } catch (EntityNotFound &e) {
        cout << (*t)("unit-doesnt-exist", "units.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayBattalionInfo(battalion);
    }
}

void BattalionsMenu::displayBattalionInfo(Battalion *battalion) {
    if (!battalion) return;
    vector<CombatUnit *> units = service->getUnitsInBattalion(battalion->getId());
    printBattalionInfo(battalion, units);
    cout << endl << (*t)("add-new-unit", "battalions.info") << endl;
    cout << (*t)("remove-unit", "battalions.info") << endl;
    cout << (*t)("delete", "battalions.info") << endl;
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this, battalion]() {
                ui->toggleLocale();
                return displayBattalionInfo(battalion);
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::BATTALIONS_MENU);
                return;
            }},
            {Keys::KEY_A, [this, battalion] {
                return addUnitToBattalion(battalion);
            }},
            {Keys::KEY_M, [this, battalion] {
                return removeUnitFromBattalion(battalion);
            }},
            {Keys::KEY_D, [this, battalion] {
                return deleteBattalion(battalion);
            }}
    });
}

void BattalionsMenu::findAndDisplayBattalionInfo() {
    Battalion *battalion = findBattalion();
    return displayBattalionInfo(battalion);
}
